<?php

class UpdateQueryBuilder implements SQLQueryBuilder {

    /**
     * @var FieldCollection
     */
    protected $fields;

    /**
     * @var Table
     */
    protected $table;

    /**
     * @var CriteriaCollection
     */
    protected $criterion;

    /**
     * @var JoinCollection
     */
    protected $joins;

    /**
     * @var string
     */
    protected $limit;

    /**
     * @var array
     */
    protected $values;

    /**
     * @param string[] $fields
     * @param string $tableName
     * @param array $values
     */
    public function __construct($fields, $tableName, $values) {
        $this->fields = new FieldCollection($fields);
        $this->table = New Table($tableName);
        $this->values = $values;
        $this->criterion = new CriteriaCollection();
        $this->joins = new JoinCollection();
    }

    /**
     * @return string
     */
    private function getUpdateTableClause() {
        return 'UPDATE ' . $this->table->getName();
    }

    /**
     * @return string
     */
    private function getJoinClause() {
        $joinCollectionString = $this->joins->getJoinCollectionString();
        return $joinCollectionString ? ' ' . $joinCollectionString : '';
    }

    /**
     * @return string
     */
    private function getSetClause() {
        $setClause = ' SET ';
        for($i=0; $i < $this->fields->getFieldCount(); $i++) {
            $setClause .= $this->fields->getFieldByIndex($i) . " = '" . $this->values[$i] . "', ";
        }
        $setClause = substr($setClause, 0, strrpos($setClause, ', '));
        return $setClause;
    }

    private function getWhereClause() {
        if($this->criterion->getCriteriaCount() > 0) {
            return ' WHERE ' . $this->criterion->getCriteriaString();
        }
        return '';
    }

    /**
     * @return string
     */
    public function getSQLQuery() {
        $sqlQuery = $this->getUpdateTableClause();
        $sqlQuery .= $this->getJoinClause();
        $sqlQuery .= $this->getSetClause();
        $sqlQuery .= $this->getWhereClause();
        $sqlQuery .= ';';
        return $sqlQuery;
    }

    /**
     * @param Criteria $criteria
     */
    public function addCriteria($criteria) {
        $this->criterion->addCriteria($criteria);
    }

    /**
     * @param Criteria $criteria
     */
    public function addOrCriteria($criteria) {
        $this->criterion->addOrCriteria($criteria);
    }

    /**
     * @param string $tableName
     * @param Criteria $criteria
     * @param string $type
     */
    public function joinTable($tableName, $criteria = null, $type = '') {
        $this->joins->createAndAddJoin($this->table->getName(), $tableName, $criteria, $type );
    }

}